package org.groovyflow.util

class RulesRunner{
   boolean stopOnFirstTrue
   def rules = []
   
   /**Use this if your closures don't require any arguments
   *After all, they're closures and can therefore react to
   *their surrounding context, so they don't always require 
   *arguments
   */
   def run(){
       run(null)
   }

   def run(args){
       run(args, args)
   } 
   def run(argsForPred, argsForAction){
        def results = []
        for(rule in rules){
           boolean tf = ClosureHelp.invokeClosure(rule.pred, argsForPred)
           if(tf){
               results << ClosureHelp.invokeClosure(rule.action, argsForAction)
               if(stopOnFirstTrue)
                    break
           }    
        }
        results
    }   

}


/*
//Usage examples***********
def runner = new RulesRunner()

runner.rules << new Rule( pred : {x -> x > 3}, action : { x -> "yep, $x > 3"} )
runner.rules << new Rule( pred : {x -> x < 0}, action :{ x -> "yep, $x is negative"} )
runner.rules << new Rule( pred : {x -> x > 0}, action :{ x -> "yep, $x is positive"} )

//scalar argument, should trigger two actions
def ret = runner.run(4)
assert ["yep, 4 > 3", "yep, 4 is positive"] == ret

//Just to show that we can call the method that allows us to give
//the preds and the actions distinct arguments
ret = runner.run(4,4)
assert ["yep, 4 > 3", "yep, 4 is positive"] == ret

//Should only use first argument in this list
ret = runner.run([10, -1, -3])
assert ["yep, 10 > 3", "yep, 10 is positive"] == ret

//Should stop after first true, as with a series of if-else clauses
runner.stopOnFirstTrue = true
ret = runner.run(4)
assert ["yep, 4 > 3"] == ret

//IMPORTANT:  If you want to pass a list in as the one argument of a closure,
//you need to enclose it in another list.  That is,  for this closure:
//(e.g. {theList -> println theList.size()  }
//you need to pass in args equal to [theList] rather than simply theList
//See ClosureHelp
def theList = ['a', 'b']
runner.rules = []
runner.rules <<  new Rule( pred : { -> theList.size >= 0}, action : {  -> theList.size} )
ret = runner.run()
assert [2] == ret

//Try closures that don't have any parameters
def theNum = 5
runner.rules = []
runner.rules << new Rule( pred : { -> theNum > 0}, action : {  -> "yep, $theNum is positive"} )
ret = runner.run()
assert ["yep, 5 is positive"] == ret
//***************************************
*/